package cn.edu.zut.hhr.service.impl;

import cn.edu.zut.hhr.entity.Article;
import cn.edu.zut.hhr.service.ArticleChooseService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

//@Service
public class ArticleChooseServiceImpl implements ArticleChooseService {
    @Value("${host.cpu.cnt:2}")
    private int cpuCnt;
    private static final int MAX_TASK_CNT = 10000;
    private ThreadPoolExecutor threadPool;

    abstract class AbstractArtService implements Runnable{
        private int cnt;
        private CountDownLatch countDownLatch;
        private volatile List<Article> ans;
        private long userId;
        public AbstractArtService(int cnt, long userId){
            this.userId = userId;
            this.cnt = cnt;
            ans = new ArrayList<>();
        }
        protected abstract List<Article> getArticle(int cnt,long userId);

        public void run(){
            this.ans = getArticle(cnt,userId);
            countDownLatch.countDown();
        }
        public List<Article> getArticles(){
            return this.ans;
        }
        public void setCountDownLatch(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }
    }

    //todo
    class RecommendArtService extends AbstractArtService{


        public RecommendArtService(int cnt, long userId) {
            super(cnt, userId);
        }

        @Override
        protected List<Article> getArticle(int cnt, long userId) {
            return null;
        }
    }

    class HotArtService extends AbstractArtService{


        public HotArtService(int cnt, long userId) {
            super(cnt, userId);
        }

        @Override
        protected List<Article> getArticle(int cnt, long userId) {
            return null;
        }
    }

    class RandomArtService extends AbstractArtService{

        public RandomArtService(int cnt, long userId) {
            super(cnt, userId);
        }

        @Override
        protected List<Article> getArticle(int cnt, long userId) {
            return null;
        }
    }

    class ViewedArtService extends AbstractArtService{


        public ViewedArtService(int cnt, long userId) {
            super(cnt, userId);
        }

        @Override
        protected List<Article> getArticle(int cnt, long userId) {
            return null;
        }
    }

    class LikeArtService extends AbstractArtService{


        public LikeArtService(int cnt, long userId) {
            super(cnt, userId);
        }

        @Override
        protected List<Article> getArticle(int cnt, long userId) {
            return null;
        }
    }

    public ArticleChooseServiceImpl(){
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(MAX_TASK_CNT);
        this.threadPool = new ThreadPoolExecutor(2*cpuCnt,6*cpuCnt,1, TimeUnit.MINUTES,queue);
    }
    @Override
    public List<Article> chooseArticle(long userId, int cnt) {
        int multiple = 1000;
        int recommendCnt = cnt>>1;
        int hotCommendCnt = (cnt>>1)*6/10;
        int randomCnt = cnt-recommendCnt-hotCommendCnt;
        int viewedCnt = 200;
        int likeCnt = 200;

        List<AbstractArtService> services = new ArrayList<>();
        //可以用工厂模式/建造者模式的, 懒得写了
        AbstractArtService recommendArtService = new RecommendArtService(recommendCnt*multiple,userId);
        services.add(recommendArtService);
        AbstractArtService hotArtService = new HotArtService(hotCommendCnt*multiple,userId);
        services.add(hotArtService);
        AbstractArtService randomArtService = new RandomArtService(randomCnt*multiple,userId);
        services.add(randomArtService);
        AbstractArtService viewedArtService = new ViewedArtService(viewedCnt,userId);
        services.add(viewedArtService);
        AbstractArtService likeArtService = new LikeArtService(likeCnt,userId);
        services.add(likeArtService);
        CountDownLatch countDownLatch = new CountDownLatch(services.size());
        services.forEach((AbstractArtService service)->{
            service.setCountDownLatch(countDownLatch);
        });
        services.forEach((AbstractArtService service)->{
            this.threadPool.execute(service);
        });
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }
        //计算余弦相似度
        List<Article> likes = likeArtService.getArticles();
        List<Article> recommends = recommendArtService.getArticles();
        List<Article> hots = hotArtService.getArticles();
        List<Article> randoms = randomArtService.getArticles();
        List<Article> views = viewedArtService.getArticles();

        sortByItemCF(likes,recommends);
        sortByItemCF(likes,hots);
        sortByItemCF(likes,randoms);
        recommends.stream().filter((Article a)->{
            return views.contains(a);
        });
        hots.stream().filter((Article a)->{
            return views.contains(a);
        });
        randoms.stream().filter((Article a)->{
            return views.contains(a);
        });

        List<Article> result = new ArrayList<>();
        result.addAll(recommends.subList(0,recommendCnt));
        result.addAll(hots.subList(0,hotCommendCnt));
        result.addAll(randoms.subList(0,randomCnt));

        return result;
    }

    //todo
    private void sortByItemCF(List<Article> likeList, List<Article> sortedList){

    }

    @Override
    public List<Article> chooseArticle(int cnt) {
        return chooseArticle(-1,cnt);
    }
}
